/**
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 2 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *    
 *    Linking this library statically or dynamically with other modules 
 *    is making a combined work based on this library. Thus, the terms and
 *    conditions of the GNU General Public License cover the whole
 *    combination.
 *    
 *    As a special exception, the copyright holders of this library give 
 *    you permission to link this library with independent modules to 
 *    produce an executable, regardless of the license terms of these 
 *    independent modules, and to copy and distribute the resulting 
 *    executable under terms of your choice, provided that you also meet, 
 *    for each linked independent module, the terms and conditions of the 
 *    license of that module.  An independent module is a module which 
 *    is not derived from or based on this library.  If you modify this 
 *    library, you may extend this exception to your version of the 
 *    library, but you are not obligated to do so.  If you do not wish 
 *    to do so, delete this exception statement from your version.
 *
 *    Project: Financas Pessoais
 *    Author : Igor Salles
 */
package org.fp.db;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
//model
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Locale;
import org.fp.model.Record;
//CSVTokenizer
import org.fp.util.CSVTokenizer;

/**
 *
 * @author iroiro
 */
public class ImportRecord {

    private ArrayList<Record> entries = new ArrayList<Record>();
    private Record record;
    
    /**
     * O extrato de cc do banco do brasil quando exportado pra texto vem com
     * o layout da tela. Entao precisamos navegar nas linhas e tentar encontrar
     * as informacoes relativas as transacoes ocorridas na conta. Notar que 
     * movimentos nao compensados ou bloqueados para compensacao entram no 
     * extrato mas nao compoem o balanco da conta. O extrato exportado pra texto
     * apresenta a apresentacao do historico da transacao em multiplas linhas
     * o que pode truncar se nao for adequadamente tratado.
     */
    private void importTxtBB() throws ParseException {
        try {
            File arqTxt = new File("bb.txt");
            FileInputStream fis = new FileInputStream(arqTxt);
            InputStreamReader isr = new InputStreamReader(fis, "ISO-8859-1");
            BufferedReader reader = new BufferedReader(isr);

            String line;
            String strAgencia = "0";
            String strConta= "0";
            int counter = 0;
            //String tmpS;
            //para facilitar navegar nas linhas dos historicos vamos carregar o
            //arquivo de texto em uma lista e navegar dentro dela.
            ArrayList<String> lines = new ArrayList<String>();
            while ((line = reader.readLine()) != null) {
                lines.add(line);
                counter++;
            }
            //com o arquivo lido podemos fechar 
            reader.close();
            isr.close();
            fis.close();

//            System.out.println("" + counter);
//            System.out.println("" + lines.size());
//            System.out.println("" + lines.get(100));
            
            //vamos navegar pela lista e pegar os registros de transacoes
            int tmpie = 0;
            for (int i = 0; i < (lines.size()) ; i++) {
                //System.out.println(lines.get(i));
                //se a linha comecar com agencia, temos os dados da conta corrente                
                if(lines.get(i).trim().startsWith("Agência")){
                    strAgencia = lines.get(i).substring(9, 13);
                    strConta = lines.get(i).substring(29).trim();
                    strConta = strConta.substring(0, strConta.length() - 2);
                    System.out.println(strAgencia+" "+strConta+" "+i);
                }else { //vamos atras das transacoes
                    if (this.isValidDate(lines.get(i).substring(0, 8))){
                        if (lines.get(i).contains("Auto-Atendimento")){
                            continue;                        
                        }
                        //nao queremos os saldos ou somatorios.
                        line = lines.get(i).substring(17, 42);
                        if (!line.contains("S A L D O") &&
                                !line.contains("Saldo Anterior")){
                            record = new Record();
                            record.setAgencia(Integer.parseInt(strAgencia));
                            record.setBanco(1);
                            record.setConta(Integer.parseInt(strConta));
                            record.setOpcao(0);
                            record.setData(
                                    new SimpleDateFormat("dd/mm/yy").parse(
                                    lines.get(i).substring(0, 8)));
                            record.setAgenciaOrigem(
                                    Integer.parseInt(
                                    lines.get(i).substring(9, 13)));
                            //para o historico e o detalhamento temos que ver
                            //se a proxima linha contem o detalhamento do 
                            //historico e pega-la tbm.
                            record.setHistorico(lines.get(i).substring(17, 42));
                            if(!(this.isValidDate(lines.get(i+1).substring(0,8)))){
                                //se a linha imediatamente posterior a um 
                                //registro entao eh o detalhamento.
                                record.setDetalhamento(lines.get(i+1).trim());
                            }else record.setDetalhamento("");
                            record.setDocumento(lines.get(i).substring(43, 63));
                            //temos de setar o decimal separator para ponto.
                            line = lines.get(i).substring(64, 78);
                            line = line.replace(".", "");
                            line = line.replace(",", ".");
                            record.setValor(Double.parseDouble(line));
                            record.setNatureza((lines.get(i).substring(79, 80).charAt(0)));


                        //achamos a linha com um lancamento e temos a data 0,9
//                        System.out.print(" "+lines.get(i).substring(0, 8)); //data
//                        System.out.print(" "+lines.get(i).substring(9, 15));//agorg
//                        System.out.print(" "+lines.get(i).substring(17, 42));//histo
//                        System.out.print(" "+lines.get(i).substring(43, 63));//doc
//                        System.out.print(" "+lines.get(i).substring(64, 78));//valor
//                        System.out.println(" "+lines.get(i).substring(79, 80));//natureza
                            entries.add(record);
                        }

                    }
                }
            }
            StringBuilder sb = null;
            Double total = 0.0;
            
            for (Record rec : entries) {
                sb = new StringBuilder();
                sb.append(new SimpleDateFormat("dd.mm.yyyy").format(rec.getData()));
                sb.append(" ");
                sb.append(rec.getAgenciaOrigem());
                sb.append(" ");
                sb.append(rec.getHistorico());
                sb.append(" ");
                sb.append(rec.getDocumento());
                sb.append(" ");
                sb.append(rec.getValor());
                sb.append(" ");
                sb.append(rec.getNatureza());
                sb.append("\n");
                sb.append(rec.getDetalhamento());
                System.out.println(sb.toString());
                if (!rec.getNatureza().equals('*')){
                    if (rec.getNatureza().equals('D'))
                        total = total - rec.getValor();
                    else
                        total = total + rec.getValor();
                }
            }
            System.out.println("Saldo: "+ NumberFormat.getCurrencyInstance(Locale.getDefault()).format(total));
            
           
            


//            if(line.trim().startsWith("SISBB")){
//                continue;
//            }else if(line.trim().startsWith("Agência")){
//                strAgencia = line.substring(9, 13);
//                strConta = line.substring(29).trim();
//                
//                System.out.println(""+line);
//                System.out.println(""+strAgencia);
//                System.out.println(""+strConta);
//            }else if (line.trim().startsWith("Data")){
//                 Scanner
//            }
//            
//            System.out.println(""+line);
//                        
//        }


        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        } catch (UnsupportedEncodingException e2) {
            e2.printStackTrace();
        } catch (IOException e3) {
            e3.printStackTrace();
        }

    }

    private void importCsvBB() {
        //quando o sisbb emite o arquivo csv ele nao anexa nenhuma informacao
        //que vincula os dados a nenhuma conta. O usuario vai ter de informar
        //os dados na hora de importar o csv.
        try {
            //criar arquivo com o bbcsv
            File arqBb = new File("bb.csv");
            FileInputStream fis = new FileInputStream(arqBb);
            InputStreamReader isr = new InputStreamReader(fis, "ISO-8859-1");
            BufferedReader reader = new BufferedReader(isr);

            CSVTokenizer csv;
            String line;
            String tmpS;
            int counter;

            while ((line = reader.readLine()) != null) {
                record = new Record();
                csv = new CSVTokenizer(line, ",", CSVTokenizer.DOUBLE_QUATE);
                counter = 0;
                //   System.out.println("");
                while (csv.hasMoreTokens()) {
                    //um detalhe importante eh que se o lancamento for o saldo
                    //anterior nao importa pra gente entao temos de pegar ele
                    //antes de adicionar no array.
                    counter++;
                    tmpS = csv.nextToken();
                    if (tmpS.contains("Data")) { //primeira linha com os titulos
                        break;
                    } else if (counter == 1) { //data do lancamento 
                        record.setData(new SimpleDateFormat("mm/dd/yyyy").parse(tmpS));
                    } else if (counter == 2) { //Dependencia de origem
                        if (tmpS.isEmpty()) { //se o lancamento nao tiver origem
                            record.setAgenciaOrigem(0); //setamos pra 0
                        } else {
                            record.setAgenciaOrigem(Integer.parseInt(tmpS.substring(0, 4)));
                        }
                    } else if (counter == 3) { //Historico 
                        //quando trabalhamos com o csv do bb ele nao separa o
                        //detalhamento do historico reduzido. entao setamos
                        //o detalhamento com o mesmo valor do historico.
                        record.setHistorico(tmpS);
                        record.setDetalhamento(tmpS);
                    } else if (counter == 4) { //data do balancete
                        //ignoraremos este valor por enquanto por nao ter destino
                        record.setRegistro(tmpS);
                    } else if (counter == 5) { //numero do documento 
                        record.setDocumento(tmpS);
                    } else if (counter == 6) { //valor
                        if (Double.parseDouble(tmpS) < 0) {
                            //se o valor que vem eh negativo entao
                            record.setValor(Double.parseDouble(tmpS));
                            record.setNatureza('D');
                        } else {
                            record.setValor(Double.parseDouble(tmpS));
                            record.setNatureza('C');
                        }
                    }
                }
                if (record.getData() != null) {
                    if (!(record.getHistorico().contains("Saldo Anterior"))) {
                        if (!(record.getHistorico().contains("S A L D O"))) {
                            entries.add(record);
                        }
                    }
                }
            }
            
            Double total = 0.0;

            for (Record record1 : entries) {
                System.out.println("" + record1.getData() + " "
                        + record1.getDetalhamento() + " "
                        + record1.getValor());
                total = total + record1.getValor();
            }
            System.out.println("SALDO FINAL : " + total);


            reader.close();
            isr.close();
            fis.close();


        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        } catch (UnsupportedEncodingException e2) {
            e2.printStackTrace();
        } catch (IOException e3) {
            e3.printStackTrace();
        } catch (ParseException e4) {
            e4.printStackTrace();
        }
    }

    private void importCaixa() {
        try {
            //importa os dados da conta corrente da caixa economica
            File arq = new File("Caixa.txt");
            FileInputStream fis = new FileInputStream(arq);
            InputStreamReader isr = new InputStreamReader(fis, "ISO-8859-1");
            BufferedReader reader = new BufferedReader(isr);

            CSVTokenizer csv;
            String line;
            String tmpString;
            int counter;
            while ((line = reader.readLine()) != null) {
                record = new Record();
                csv = new CSVTokenizer(line, ";", CSVTokenizer.DOUBLE_QUATE);
                counter = 0;
                while (csv.hasMoreTokens()) {
                    counter++;
                    //normalmente a primeira linha contem os titulos
                    tmpString = csv.nextToken();
                    if (tmpString.contains("Conta")) {
                        //eh a linha de titulo entao ignoramos
                        break; //e lemos a proxima linha
                    } else {
                        if (counter == 1) {
                            record.setAgencia(Integer.parseInt(tmpString.substring(0, 4)));
                            record.setOpcao(Integer.parseInt(tmpString.substring(5, 7)));
                            record.setBanco(104);
                            record.setConta(Integer.parseInt(tmpString.substring(8, 16)));
                            System.out.println(tmpString);
                        } else if (counter == 2) {
                            record.setData(new SimpleDateFormat("yyyymmdd").parse(tmpString));
                        } else if (counter == 3) {
                            record.setDocumento(tmpString);

                        } else if (counter == 4) {
                            record.setHistorico(tmpString);
                            record.setDetalhamento(tmpString);
                        } else if (counter == 5) {
                            record.setValor(Double.valueOf(tmpString));

                        } else if (counter == 6) {
                            record.setNatureza(Character.valueOf(tmpString.charAt(0)));
                        } else {
                            //deu xabu
                            throw new ParseException("Excedeu os valores esperados", counter);
                        }


                    }
                }
                if (record.getNatureza() != null) {
                    entries.add(record);
                }
            }

            for (Record record1 : entries) {
                System.out.println("" + record1.getBanco() + " " + record1.getAgencia() + " "
                        + record1.getConta() + " " + new SimpleDateFormat("mm/dd/yyyy").format(record1.getData()) + " "
                        + record1.getHistorico() + " " + record1.getValor() + record1.getNatureza());

            }

            reader.close();
            isr.close();
            fis.close();

        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        } catch (UnsupportedEncodingException e2) {
            e2.printStackTrace();
        } catch (IOException e3) {
            e3.printStackTrace();
        } catch (ParseException e4) {
            e4.printStackTrace();
        }
    }
    
    public boolean isValidDate(String s){
        
        if ((s == null) || (s.isEmpty())){
            return false;
        }
        //set the format to use as a constructor argument
        SimpleDateFormat dateFormat = new SimpleDateFormat("dd/mm/yy");
        
        if(s.trim().length() != dateFormat.toPattern().length()){
            return false;
        }
        
        dateFormat.setLenient(false);
        
        try{
            //parse the string parameter
            dateFormat.parse(s.trim());
        }catch(ParseException e1){
            //e1.printStackTrace();
            return false;
        }
        return true;
    }

    public static void main(String a[]) throws ParseException {
        if (a.length < 1) {
            //no args
        }
        ImportRecord irecord = new ImportRecord();
//        irecord.importCaixa();
//        irecord.importCsvBB();
        irecord.importTxtBB();

    }
}
